Skip to content

fix: build examples in CI#347

Merged
thomhurst merged 1 commit into
mainfrom
issue-341-fix-example-ci
Jul 21, 2026
Merged

fix: build examples in CI#347
thomhurst merged 1 commit into
mainfrom
issue-341-fix-example-ci

Conversation

@thomhurst

Copy link
Copy Markdown
Owner

Summary

  • Replace broken IAsyncEnumerable.ToList() and inaccessible ToAsyncEnumerable() calls with materialized IReadOnlyList<int> results in disposal examples.
  • Add BuildExampleProjectsModule to the ModularPipelines CI graph.
  • Make packaging depend on successful example compilation so API examples cannot silently rot.

Root cause

The example project was present in the solution but absent from the CI module graph. Disposal examples also depended on conversions that are not public in the v4 API.

Test plan

  • dotnet build EnumerableAsyncProcessor.Example/EnumerableAsyncProcessor.Example.csproj -c Release
  • dotnet build EnumerableAsyncProcessor.Pipeline/EnumerableAsyncProcessor.Pipeline.csproj -c Release
  • dotnet build TomLonghurst.EnumerableAsyncProcessor.sln -c Release
  • dotnet test TomLonghurst.EnumerableAsyncProcessor.sln -c Release — 1,073/1,074 passed; unrelated net8.0 process-wide allocation assertion exceeded its nondeterministic threshold by 5,144 bytes. Follow-up: Fix flaky process-wide allocation assertion #346. net9.0 passed.

Closes #341

@greptile-apps

greptile-apps Bot commented Jul 21, 2026

Copy link
Copy Markdown

Greptile Summary

This PR adds example compilation to the CI packaging path. The main changes are:

  • Materialize disposal-example results as read-only lists.
  • Add a module that builds example projects in Release mode.
  • Make package creation depend on the example build.

Confidence Score: 5/5

The changed flow looks mergeable after tightening build-failure handling and correcting the leak description.

  • Example compilation is connected to the packaging dependency graph.
  • Unsuccessful command results should be rejected explicitly if the build API does not throw.
  • Eager enumeration makes the unfinished-task warning inaccurate.

BuildExampleProjectsModule.cs and DisposalExample.cs

Important Files Changed

Filename Overview
EnumerableAsyncProcessor.Example/DisposalExample.cs Materializes processor output as read-only lists, while one resource-leak description still refers to tasks that now finish before return.
EnumerableAsyncProcessor.Pipeline/Modules/BuildExampleProjectsModule.cs Discovers and builds example projects, but does not explicitly reject unsuccessful command results.
EnumerableAsyncProcessor.Pipeline/Modules/PackProjectsModule.cs Adds the example build as a packaging dependency.
EnumerableAsyncProcessor.Pipeline/Program.cs Registers the example-build module in the shared pipeline graph.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart LR
    A[CI pipeline] --> B[Build examples]
    A --> C[Run tests]
    A --> D[Generate version]
    A --> E[Remove package files]
    B --> F[Pack projects]
    C --> F
    D --> F
    E --> F
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
flowchart LR
    A[CI pipeline] --> B[Build examples]
    A --> C[Run tests]
    A --> D[Generate version]
    A --> E[Remove package files]
    B --> F[Pack projects]
    C --> F
    D --> F
    E --> F
Loading

Reviews (1): Last reviewed commit: "fix: keep examples compiling in CI" | Re-trigger Greptile

Comment on lines +22 to +27
{
results.Add(await context.DotNet().Build(new DotNetBuildOptions
{
ProjectSolution = exampleProjectFile.Path,
Configuration = "Release",
}, cancellationToken: cancellationToken));

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Failed Builds May Remain Successful

If DotNet().Build returns a nonzero CommandResult rather than throwing, this module stores that result and completes successfully. PackProjectsModule only depends on module completion and never checks these results, so packaging can continue after an example fails to compile.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 563971e. BuildExampleProjectsModule now passes CommandExecutionOptions { ThrowOnNonZeroExitCode = true }, so any failed example build throws and fails the module before packaging can run.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correction: #347 auto-merged before the pushed review-fix commit was attached. The same fix is now isolated on current main in #349 (e0059fc), with the example and pipeline builds passing.

Comment on lines 78 to +80
// 🔥 RESOURCE LEAK: The processor goes out of scope without being disposed,
// potentially leaving tasks running and resources uncleaned
return results;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Leak Description No Longer Matches

The new eager await foreach waits for every result before this method returns, so processor tasks are no longer left running when it goes out of scope. The processor still is not disposed, but this example now demonstrates leaked disposal resources rather than unfinished work.

Suggested change
// 🔥 RESOURCE LEAK: The processor goes out of scope without being disposed,
// potentially leaving tasks running and resources uncleaned
return results;
// 🔥 RESOURCE LEAK: The processor goes out of scope without being disposed,
// leaving its disposal resources uncleaned
return results;

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 563971e. The comment now states that undisposed processor resources remain uncleaned; it no longer claims eager-enumerated tasks are still running.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correction: #347 auto-merged before the pushed review-fix commit was attached. The corrected leak description is now in follow-up #349 (e0059fc).

@thomhurst
thomhurst merged commit 3299d51 into main Jul 21, 2026
8 checks passed
@thomhurst thomhurst mentioned this pull request Jul 21, 2026
4 tasks
thomhurst added a commit that referenced this pull request Jul 21, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Example project does not compile on main and is not built by CI

1 participant